#include "gu_client.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <readline/readline.h>
#include <readline/history.h>

// Client Creation and Destruction

gu_client_context_t* gu_client_create(void) {
    gu_client_context_t* ctx = malloc(sizeof(gu_client_context_t));
    if (!ctx) return NULL;
    
    memset(ctx, 0, sizeof(gu_client_context_t));
    
    // Initialize default configuration
    strcpy(ctx->config.host, "localhost");
    ctx->config.port = GU_DEFAULT_PORT;
    strcpy(ctx->config.username, "admin");
    strcpy(ctx->config.password, "admin");
    strcpy(ctx->config.database, "gudb");
    ctx->config.interactive = false;
    ctx->config.verbose = false;
    
    ctx->connection.sockfd = -1;
    ctx->connection.connected = false;
    ctx->connection.authenticated = false;
    ctx->running = true;
    ctx->connected = false;
    
    return ctx;
}

void gu_client_destroy(gu_client_context_t* ctx) {
    if (!ctx) return;
    
    if (ctx->connected) {
        gu_client_disconnect(ctx);
    }
    
    free(ctx);
}

// Connection Management

int gu_client_connect(gu_client_context_t* ctx) {
    if (!ctx) return -1;
    
    if (ctx->connected) {
        printf("Already connected to GuDB server\n");
        return 0;
    }
    
    // Create socket
    ctx->connection.sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (ctx->connection.sockfd < 0) {
        fprintf(stderr, "Failed to create socket: %s\n", strerror(errno));
        return -1;
    }
    
    // Resolve hostname
    struct hostent* host_entry = gethostbyname(ctx->config.host);
    if (!host_entry) {
        fprintf(stderr, "Failed to resolve hostname: %s\n", ctx->config.host);
        close(ctx->connection.sockfd);
        ctx->connection.sockfd = -1;
        return -1;
    }
    
    // Setup server address
    memset(&ctx->connection.server_addr, 0, sizeof(ctx->connection.server_addr));
    ctx->connection.server_addr.sin_family = AF_INET;
    ctx->connection.server_addr.sin_port = htons(ctx->config.port);
    memcpy(&ctx->connection.server_addr.sin_addr, host_entry->h_addr_list[0], host_entry->h_length);
    
    // Connect to server
    if (connect(ctx->connection.sockfd, (struct sockaddr*)&ctx->connection.server_addr, 
                sizeof(ctx->connection.server_addr)) < 0) {
        fprintf(stderr, "Failed to connect to %s:%d - %s\n", 
                ctx->config.host, ctx->config.port, strerror(errno));
        close(ctx->connection.sockfd);
        ctx->connection.sockfd = -1;
        return -1;
    }
    
    ctx->connection.connected = true;
    ctx->connected = true;
    
    if (ctx->config.verbose) {
        printf("Connected to GuDB server at %s:%d\n", ctx->config.host, ctx->config.port);
    }
    
    // Authenticate
    return gu_client_authenticate(ctx);
}

int gu_client_disconnect(gu_client_context_t* ctx) {
    if (!ctx || !ctx->connected) return 0;
    
    // Send quit command
    gu_packet_t* quit_packet = gu_create_quit_packet();
    if (quit_packet) {
        gu_packet_send(ctx->connection.sockfd, quit_packet);
        gu_packet_destroy(quit_packet);
    }
    
    // Close socket
    if (ctx->connection.sockfd >= 0) {
        close(ctx->connection.sockfd);
        ctx->connection.sockfd = -1;
    }
    
    ctx->connection.connected = false;
    ctx->connection.authenticated = false;
    ctx->connected = false;
    
    if (ctx->config.verbose) {
        printf("Disconnected from GuDB server\n");
    }
    
    return 0;
}

int gu_client_authenticate(gu_client_context_t* ctx) {
    if (!ctx || !ctx->connection.connected) return -1;
    
    // Create connection packet
    gu_packet_t* connect_packet = gu_create_connect_packet(
        ctx->config.username, 
        ctx->config.password, 
        ctx->config.database
    );
    
    if (!connect_packet) {
        fprintf(stderr, "Failed to create connection packet\n");
        return -1;
    }
    
    // Send connection packet
    if (gu_packet_send(ctx->connection.sockfd, connect_packet) < 0) {
        fprintf(stderr, "Failed to send connection packet\n");
        gu_packet_destroy(connect_packet);
        return -1;
    }
    
    gu_packet_destroy(connect_packet);
    
    // Receive response
    gu_packet_t* response = gu_packet_recv(ctx->connection.sockfd);
    if (!response) {
        fprintf(stderr, "Failed to receive authentication response\n");
        return -1;
    }
    
    int result = 0;
    if (response->header.command == GU_RESP_AUTH_OK) {
        ctx->connection.authenticated = true;
        if (ctx->config.verbose) {
            printf("Authentication successful\n");
        }
    } else {
        fprintf(stderr, "Authentication failed\n");
        result = -1;
    }
    
    gu_packet_destroy(response);
    return result;
}

// Command Execution

int gu_client_execute_sql(gu_client_context_t* ctx, const char* sql) {
    if (!ctx || !sql || !ctx->connection.authenticated) return -1;
    
    // Create execution packet
    gu_packet_t* exec_packet = gu_create_exec_packet(sql);
    if (!exec_packet) {
        fprintf(stderr, "Failed to create execution packet\n");
        return -1;
    }
    
    // Send packet
    if (gu_packet_send(ctx->connection.sockfd, exec_packet) < 0) {
        fprintf(stderr, "Failed to send execution packet\n");
        gu_packet_destroy(exec_packet);
        return -1;
    }
    
    gu_packet_destroy(exec_packet);
    
    // Receive response
    gu_packet_t* response = gu_packet_recv(ctx->connection.sockfd);
    if (!response) {
        fprintf(stderr, "Failed to receive response\n");
        return -1;
    }
    
    gu_result_t* result = NULL;
    int ret = gu_parse_response(response, &result);
    
    if (result) {
        gu_client_print_result(result);
        gu_result_destroy(result);
    }
    
    gu_packet_destroy(response);
    return ret;
}

int gu_client_query_sql(gu_client_context_t* ctx, const char* sql) {
    if (!ctx || !sql || !ctx->connection.authenticated) return -1;
    
    // Create query packet
    gu_packet_t* query_packet = gu_create_query_packet(sql);
    if (!query_packet) {
        fprintf(stderr, "Failed to create query packet\n");
        return -1;
    }
    
    // Send packet
    if (gu_packet_send(ctx->connection.sockfd, query_packet) < 0) {
        fprintf(stderr, "Failed to send query packet\n");
        gu_packet_destroy(query_packet);
        return -1;
    }
    
    gu_packet_destroy(query_packet);
    
    // Receive response
    gu_packet_t* response = gu_packet_recv(ctx->connection.sockfd);
    if (!response) {
        fprintf(stderr, "Failed to receive response\n");
        return -1;
    }
    
    gu_result_t* result = NULL;
    int ret = gu_parse_response(response, &result);
    
    if (result) {
        gu_client_print_result(result);
        gu_result_destroy(result);
    }
    
    gu_packet_destroy(response);
    return ret;
}

int gu_client_ping(gu_client_context_t* ctx) {
    if (!ctx || !ctx->connection.connected) return -1;
    
    gu_packet_t* ping_packet = gu_create_ping_packet();
    if (!ping_packet) return -1;
    
    if (gu_packet_send(ctx->connection.sockfd, ping_packet) < 0) {
        gu_packet_destroy(ping_packet);
        return -1;
    }
    
    gu_packet_destroy(ping_packet);
    
    gu_packet_t* response = gu_packet_recv(ctx->connection.sockfd);
    if (!response) return -1;
    
    gu_result_t* result = NULL;
    int ret = gu_parse_response(response, &result);
    
    gu_packet_destroy(response);
    if (result) gu_result_destroy(result);
    
    return ret;
}

// Interactive Mode

int gu_client_interactive_mode(gu_client_context_t* ctx) {
    if (!ctx) return -1;
    
    printf("GuDB Client v1.0\n");
    printf("Type 'help' for assistance, 'quit' to exit\n");
    printf("Use ↑/↓ arrows for command history\n\n");
    
    // Initialize readline
    rl_bind_key('\t', rl_complete);  // Enable tab completion
    
    char* input = NULL;
    
    while (ctx->running) {
        // Get current prompt
        const char* prompt = gu_client_get_prompt(ctx);
        
        // Read line with readline (supports history and editing)
        input = readline(prompt);
        
        // Handle EOF (Ctrl+D)
        if (!input) {
            printf("\n");
            break;
        }
        
        // Skip empty lines
        if (strlen(input) == 0) {
            free(input);
            continue;
        }
        
        // Add non-empty command to history
        add_history(input);
        
        // Process command
        int result = gu_client_process_command(ctx, input);
        
        // Free readline memory
        free(input);
        
        // Only exit on critical errors or explicit quit commands
        // Don't exit on SQL syntax errors (result == -1)
        if (result == -2) {  // Critical connection error
            break;
        }
        // Continue for all other cases (result == 0, -1)
    }
    
    return 0;
}

int gu_client_process_command(gu_client_context_t* ctx, const char* input) {
    if (!ctx || !input) return -1;
    
    // Trim whitespace
    while (*input == ' ' || *input == '\t') input++;
    
    if (strlen(input) == 0) return 0;
    
    // Handle built-in commands
    if (strncasecmp(input, "quit", 4) == 0 || strncasecmp(input, "exit", 4) == 0) {
        return gu_client_cmd_quit(ctx);
    }
    else if (strncasecmp(input, "help", 4) == 0) {
        return gu_client_cmd_help(ctx);
    }
    else if (strncasecmp(input, "connect", 7) == 0) {
        return gu_client_cmd_connect(ctx, input + 7);
    }
    else if (strncasecmp(input, "disconnect", 10) == 0) {
        return gu_client_cmd_disconnect(ctx);
    }
    else if (strncasecmp(input, "status", 6) == 0) {
        return gu_client_cmd_status(ctx);
    }
    else if (strncasecmp(input, "ping", 4) == 0) {
        return gu_client_ping(ctx);
    }
    // Handle built-in SQL commands - send as real SQL to server
    else if (strncasecmp(input, "show databases", 14) == 0 || 
             strncasecmp(input, "show databases;", 15) == 0) {
        if (!ctx->connected) {
            fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
            return 0;
        }
        return gu_client_query_sql(ctx, "SHOW DATABASES");
    }
    else if (strncasecmp(input, "show tables", 11) == 0 || 
             strncasecmp(input, "show tables;", 12) == 0) {
        if (!ctx->connected) {
            fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
            return 0;
        }
        return gu_client_query_sql(ctx, "SHOW TABLES");
    }
    else if (strncasecmp(input, "show status", 11) == 0 || 
             strncasecmp(input, "show status;", 12) == 0) {
        return gu_client_cmd_show_status(ctx);  // Keep as client-side command
    }
    else if (strncasecmp(input, "use ", 4) == 0) {
        if (!ctx->connected) {
            fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
            return 0;
        }
        // Send USE command to server instead of handling locally
        char sql_cmd[512];
        snprintf(sql_cmd, sizeof(sql_cmd), "USE %s", input + 4);
        // Remove trailing semicolon from sql_cmd if present
        char* semicolon = strchr(sql_cmd, ';');
        if (semicolon) *semicolon = '\0';
        return gu_client_execute_sql(ctx, sql_cmd);
    }
    else if (strncasecmp(input, "describe ", 9) == 0 || 
             strncasecmp(input, "desc ", 5) == 0) {
        if (!ctx->connected) {
            fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
            return 0;
        }
        // Send as SQL to server
        char sql_cmd[512];
        const char* table_name = strncasecmp(input, "describe ", 9) == 0 ? 
                                 input + 9 : input + 5;
        // Trim whitespace and semicolon
        while (*table_name == ' ' || *table_name == '\t') table_name++;
        snprintf(sql_cmd, sizeof(sql_cmd), "DESCRIBE %s", table_name);
        // Remove trailing semicolon from sql_cmd if present
        char* semicolon = strchr(sql_cmd, ';');
        if (semicolon) *semicolon = '\0';
        return gu_client_query_sql(ctx, sql_cmd);
    }
    else if (strncasecmp(input, "show create table ", 18) == 0) {
        if (!ctx->connected) {
            fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
            return 0;
        }
        // Send as SQL to server  
        char sql_cmd[512];
        const char* table_name = input + 18;
        // Trim whitespace and semicolon
        while (*table_name == ' ' || *table_name == '\t') table_name++;
        snprintf(sql_cmd, sizeof(sql_cmd), "SHOW CREATE TABLE %s", table_name);
        // Remove trailing semicolon from sql_cmd if present
        char* semicolon = strchr(sql_cmd, ';');
        if (semicolon) *semicolon = '\0';
        return gu_client_query_sql(ctx, sql_cmd);
    }
    else if (strncasecmp(input, "show columns from ", 18) == 0) {
        if (!ctx->connected) {
            fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
            return 0;
        }
        // Send as SQL to server
        char sql_cmd[512];
        const char* table_name = input + 18;
        // Trim whitespace and semicolon
        while (*table_name == ' ' || *table_name == '\t') table_name++;
        snprintf(sql_cmd, sizeof(sql_cmd), "SHOW COLUMNS FROM %s", table_name);
        // Remove trailing semicolon from sql_cmd if present
        char* semicolon = strchr(sql_cmd, ';');
        if (semicolon) *semicolon = '\0';
        return gu_client_query_sql(ctx, sql_cmd);
    }
    else {
        // Execute as SQL
        if (!ctx->connected) {
            fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
            return 0;
        }
        
        // Determine if it's a query or execution
        int sql_result;
        if (strncasecmp(input, "select", 6) == 0 || 
            strncasecmp(input, "show", 4) == 0 ||
            strncasecmp(input, "describe", 8) == 0 ||
            strncasecmp(input, "explain", 7) == 0) {
            sql_result = gu_client_query_sql(ctx, input);
        } else {
            sql_result = gu_client_execute_sql(ctx, input);
        }
        
        // Convert SQL errors to non-critical errors
        // Only return -2 for critical connection errors
        if (sql_result < 0) {
            // Check if connection is still alive
            if (!ctx->connected || !ctx->connection.connected) {
                fprintf(stderr, "Connection lost. Use 'connect' to reconnect.\n");
                return -2;  // Critical connection error
            }
            // For SQL syntax errors, don't exit the client
            return 0;  // Continue running despite SQL error
        }
        
        return sql_result;
    }
}

// Command Line Interface

int gu_client_parse_args(gu_client_context_t* ctx, int argc, char* argv[]) {
    if (!ctx) return -1;
    
    static struct option long_options[] = {
        {"host",     required_argument, 0, 'h'},
        {"port",     required_argument, 0, 'P'},
        {"user",     required_argument, 0, 'u'},
        {"password", required_argument, 0, 'p'},
        {"database", required_argument, 0, 'd'},
        {"interactive", no_argument,    0, 'i'},
        {"verbose",  no_argument,       0, 'v'},
        {"help",     no_argument,       0, '?'},
        {0, 0, 0, 0}
    };
    
    int c;
    while ((c = getopt_long(argc, argv, "h:P:u:p:d:iv?", long_options, NULL)) != -1) {
        switch (c) {
            case 'h':
                strncpy(ctx->config.host, optarg, sizeof(ctx->config.host) - 1);
                break;
            case 'P':
                ctx->config.port = atoi(optarg);
                break;
            case 'u':
                strncpy(ctx->config.username, optarg, sizeof(ctx->config.username) - 1);
                break;
            case 'p':
                strncpy(ctx->config.password, optarg, sizeof(ctx->config.password) - 1);
                break;
            case 'd':
                strncpy(ctx->config.database, optarg, sizeof(ctx->config.database) - 1);
                break;
            case 'i':
                ctx->config.interactive = true;
                break;
            case 'v':
                ctx->config.verbose = true;
                break;
            case '?':
                gu_client_print_usage(argv[0]);
                return 1;
            default:
                return -1;
        }
    }
    
    return 0;
}

void gu_client_print_usage(const char* program_name) {
    printf("Usage: %s [OPTIONS] [SQL_COMMAND]\n\n", program_name);
    printf("GuDB Client - Connect to GuDB database server\n\n");
    printf("Options:\n");
    printf("  -h, --host HOST        Server hostname (default: localhost)\n");
    printf("  -P, --port PORT        Server port (default: %d)\n", GU_DEFAULT_PORT);
    printf("  -u, --user USER        Username (default: admin)\n");
    printf("  -p, --password PASS    Password (default: admin)\n");
    printf("  -d, --database DB      Database name (default: gudb)\n");
    printf("  -i, --interactive      Start in interactive mode\n");
    printf("  -v, --verbose          Enable verbose output\n");
    printf("  -?, --help             Show this help message\n\n");
    printf("Examples:\n");
    printf("  %s -i                           # Interactive mode\n", program_name);
    printf("  %s \"SELECT * FROM users\"        # Execute single query\n", program_name);
    printf("  %s -h server -P 7777 -i        # Connect to remote server\n", program_name);
}

void gu_client_print_help(void) {
    printf("GuDB Client Commands:\n\n");
    printf("Connection Commands:\n");
    printf("  connect [host:port]    - Connect to GuDB server\n");
    printf("  disconnect             - Disconnect from server\n");
    printf("  ping                   - Test server connection\n");
    printf("  status                 - Show connection status\n\n");
    printf("Built-in Commands:\n");
    printf("  show databases         - List all databases\n");
    printf("  show tables            - List tables in current database\n");
    printf("  show status            - Show server status information\n");
    printf("  use <database>         - Switch to specified database\n");
    printf("  describe <table>       - Show table structure (same as desc)\n");
    printf("  desc <table>           - Show table structure\n");
    printf("  show create table <table> - Show CREATE TABLE statement\n");
    printf("  show columns from <table> - Show table columns\n\n");
    printf("Data Definition Language (DDL):\n");
    printf("  CREATE DATABASE <name> [IF NOT EXISTS] - Create a new database\n");
    printf("  CREATE TABLE ...       - Create a new table with columns\n");
    printf("  DROP DATABASE <name> [IF EXISTS] - Drop an existing database\n");
    printf("  DROP TABLE <name> [IF EXISTS] - Drop an existing table\n\n");
    printf("Data Manipulation Language (DML):\n");
    printf("  INSERT INTO ...        - Insert data into table\n");
    printf("  SELECT ...             - Query data from tables\n");
    printf("  UPDATE ... SET ... [WHERE ...] - Update existing data\n");
    printf("  DELETE FROM ... [WHERE ...] - Delete data from table\n\n");
    printf("Transaction Commands:\n");
    printf("  START TRANSACTION      - Begin a new transaction\n");
    printf("  COMMIT                 - Commit current transaction\n");
    printf("  ROLLBACK               - Rollback current transaction\n\n");
    printf("Other Commands:\n");
    printf("  help                   - Show this help\n");
    printf("  quit, exit             - Exit client\n\n");
    printf("Database Features:\n");
    printf("  - Database isolation: Each database has independent table space\n");
    printf("  - Transaction support: ACID compliant transactions\n");
    printf("  - Multiple data types: INT, VARCHAR, CHAR, FLOAT, etc.\n");
    printf("  - Write-Ahead Logging (WAL) for durability\n");
    printf("  - Persistent metadata storage\n\n");
    printf("Notes:\n");
    printf("  - Commands can end with or without semicolon (;)\n");
    printf("  - SQL syntax errors will not exit the client\n");
    printf("  - Use 'status' to check connection state\n");
    printf("  - Database names and table names are case-sensitive\n");
    printf("  - Use quotes for names with spaces or special characters\n\n");
}

// Utility Functions

void gu_client_print_result(gu_result_t* result) {
    if (!result) return;
    
    // Check operation type based on result data
    if (result->column_names && result->column_count > 0) {
        // DQL operation (SELECT) - show result set
        gu_client_print_select_result(result);
    } else if (result->row_count > 0) {
        // DML operation (INSERT, UPDATE, DELETE) - show affected rows
        printf("Query OK, %u row%s affected\n", 
               result->row_count, 
               result->row_count == 1 ? "" : "s");
    } else {
        // DDL operation (CREATE, ALTER, DROP) - show success message
        printf("Query OK, 0 rows affected\n");
    }
}

void gu_client_print_select_result(gu_result_t* result) {
    if (!result || !result->column_names) return;
    
    // Print column headers
    printf("+");
    for (uint32_t i = 0; i < result->column_count; i++) {
        for (int j = 0; j < 20; j++) printf("-");
        printf("+");
    }
    printf("\n|");
    
    for (uint32_t i = 0; i < result->column_count; i++) {
        printf(" %-18s |", result->column_names[i]);
    }
    printf("\n+");
    
    for (uint32_t i = 0; i < result->column_count; i++) {
        for (int j = 0; j < 20; j++) printf("-");
        printf("+");
    }
    printf("\n");
    
    // Print data rows
    if (result->rows && result->row_count > 0) {
        for (uint32_t r = 0; r < result->row_count; r++) {
            printf("|");
            for (uint32_t c = 0; c < result->column_count; c++) {
                const char* value = result->rows[r][c] ? 
                                   result->rows[r][c] : "NULL";
                printf(" %-18s |", value);
            }
            printf("\n");
        }
        
        printf("+");
        for (uint32_t i = 0; i < result->column_count; i++) {
            for (int j = 0; j < 20; j++) printf("-");
            printf("+");
        }
        printf("\n");
        
        printf("%u row%s in set\n", 
               result->row_count, 
               result->row_count == 1 ? "" : "s");
    } else {
        printf("Empty set (0 rows)\n");
    }
}

const char* gu_client_get_prompt(gu_client_context_t* ctx) {
    if (!ctx) return "gu> ";
    
    static char prompt[128];
    if (ctx->connected) {
        snprintf(prompt, sizeof(prompt), "gu[%s]> ", ctx->config.database);
    } else {
        strcpy(prompt, "gu> ");
    }
    return prompt;
}

// Built-in Commands

int gu_client_cmd_connect(gu_client_context_t* ctx, const char* args) {
    if (!ctx) return -1;
    
    // Parse connection string if provided
    if (args && strlen(args) > 0) {
        // Simple parsing for host:port
        char* colon = strchr(args, ':');
        if (colon) {
            *colon = '\0';
            strncpy(ctx->config.host, args, sizeof(ctx->config.host) - 1);
            ctx->config.port = atoi(colon + 1);
        } else {
            strncpy(ctx->config.host, args, sizeof(ctx->config.host) - 1);
        }
    }
    
    return gu_client_connect(ctx);
}

int gu_client_cmd_disconnect(gu_client_context_t* ctx) {
    if (!ctx) return -1;
    return gu_client_disconnect(ctx);
}

int gu_client_cmd_quit(gu_client_context_t* ctx) {
    if (!ctx) return -1;
    
    printf("Goodbye!\n");
    ctx->running = false;
    return 0;
}

int gu_client_cmd_help(gu_client_context_t* ctx) {
    (void)ctx;  // Suppress unused parameter warning
    gu_client_print_help();
    return 0;
}

int gu_client_cmd_status(gu_client_context_t* ctx) {
    if (!ctx) return -1;
    
    printf("Connection Status:\n");
    printf("  Host: %s\n", ctx->config.host);
    printf("  Port: %d\n", ctx->config.port);
    printf("  User: %s\n", ctx->config.username);
    printf("  Database: %s\n", ctx->config.database);
    printf("  Connected: %s\n", ctx->connected ? "Yes" : "No");
    printf("  Authenticated: %s\n", ctx->connection.authenticated ? "Yes" : "No");
    
    return 0;
}

// Built-in SQL Commands

int gu_client_cmd_show_databases(gu_client_context_t* ctx) {
    if (!ctx) return -1;
    
    if (!ctx->connected) {
        fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
        return 0;
    }
    
    printf("Databases:\n");
    printf("+----------+\n");
    printf("| Database |\n");
    printf("+----------+\n");
    printf("| gudb     |\n");
    printf("| test     |\n");
    printf("| admin    |\n");
    printf("+----------+\n");
    printf("3 databases found\n");
    
    return 0;
}

int gu_client_cmd_show_tables(gu_client_context_t* ctx) {
    if (!ctx) return -1;
    
    if (!ctx->connected) {
        fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
        return 0;
    }
    
    printf("Tables in database '%s':\n", ctx->config.database);
    printf("+-----------------+\n");
    printf("| Table           |\n");
    printf("+-----------------+\n");
    printf("| users           |\n");
    printf("| products        |\n");
    printf("| orders          |\n");
    printf("+-----------------+\n");
    printf("3 tables found\n");
    
    return 0;
}

int gu_client_cmd_show_status(gu_client_context_t* ctx) {
    if (!ctx) return -1;
    
    if (!ctx->connected) {
        fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
        return 0;
    }
    
    printf("Server Status:\n");
    printf("+-------------------------+------------------------+\n");
    printf("| Variable                | Value                  |\n");
    printf("+-------------------------+------------------------+\n");
    printf("| Version                 | GuDB 1.0               |\n");
    printf("| Port                    | 7777                   |\n");
    printf("| Uptime                  | Running                |\n");
    printf("| Current database        | %s%-15s |\n", ctx->config.database, "");
    printf("| Connected clients       | 1                      |\n");
    printf("| Total connections       | 5                      |\n");
    printf("| Protocol version        | GuDB Native 1.0        |\n");
    printf("+-------------------------+------------------------+\n");
    
    return 0;
}

int gu_client_cmd_use_database(gu_client_context_t* ctx, const char* database) {
    if (!ctx || !database) return -1;
    
    if (!ctx->connected) {
        fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
        return 0;
    }
    
    // Trim whitespace and semicolon
    while (*database == ' ' || *database == '\t') database++;
    
    char db_name[256];
    strncpy(db_name, database, sizeof(db_name) - 1);
    db_name[sizeof(db_name) - 1] = '\0';
    
    // Remove trailing semicolon if present
    char* semicolon = strchr(db_name, ';');
    if (semicolon) *semicolon = '\0';
    
    // Remove trailing whitespace
    int len = strlen(db_name);
    while (len > 0 && (db_name[len-1] == ' ' || db_name[len-1] == '\t')) {
        db_name[--len] = '\0';
    }
    
    if (strlen(db_name) == 0) {
        fprintf(stderr, "Database name cannot be empty\n");
        return 0;
    }
    
    // Update current database
    strncpy(ctx->config.database, db_name, sizeof(ctx->config.database) - 1);
    ctx->config.database[sizeof(ctx->config.database) - 1] = '\0';
    
    printf("Database changed to '%s'\n", db_name);
    
    return 0;
}

int gu_client_cmd_describe_table(gu_client_context_t* ctx, const char* table) {
    if (!ctx || !table) return -1;
    
    if (!ctx->connected) {
        fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
        return 0;
    }
    
    // Trim whitespace and semicolon
    while (*table == ' ' || *table == '\t') table++;
    
    char table_name[256];
    strncpy(table_name, table, sizeof(table_name) - 1);
    table_name[sizeof(table_name) - 1] = '\0';
    
    // Remove trailing semicolon if present
    char* semicolon = strchr(table_name, ';');
    if (semicolon) *semicolon = '\0';
    
    // Remove trailing whitespace
    int len = strlen(table_name);
    while (len > 0 && (table_name[len-1] == ' ' || table_name[len-1] == '\t')) {
        table_name[--len] = '\0';
    }
    
    if (strlen(table_name) == 0) {
        fprintf(stderr, "Table name cannot be empty\n");
        return 0;
    }
    
    printf("Table structure for '%s':\n", table_name);
    printf("+-------------+------------------+------+-----+---------+----------------+\n");
    printf("| Field       | Type             | Null | Key | Default | Extra          |\n");
    printf("+-------------+------------------+------+-----+---------+----------------+\n");
    
    // Mock table structure data - in a real implementation this would query the server
    if (strcasecmp(table_name, "users") == 0) {
        printf("| id          | int(11)          | NO   | PRI | NULL    | auto_increment |\n");
        printf("| name        | varchar(50)      | YES  |     | NULL    |                |\n");
        printf("| email       | varchar(100)     | YES  | UNI | NULL    |                |\n");
        printf("| created_at  | timestamp        | NO   |     | CURRENT |                |\n");
    } else if (strcasecmp(table_name, "products") == 0) {
        printf("| id          | int(11)          | NO   | PRI | NULL    | auto_increment |\n");
        printf("| name        | varchar(100)     | NO   |     | NULL    |                |\n");
        printf("| price       | decimal(10,2)    | NO   |     | 0.00    |                |\n");
        printf("| category    | varchar(50)      | YES  |     | NULL    |                |\n");
    } else if (strcasecmp(table_name, "orders") == 0) {
        printf("| id          | int(11)          | NO   | PRI | NULL    | auto_increment |\n");
        printf("| user_id     | int(11)          | NO   | MUL | NULL    |                |\n");
        printf("| product_id  | int(11)          | NO   | MUL | NULL    |                |\n");
        printf("| quantity    | int(11)          | NO   |     | 1       |                |\n");
        printf("| order_date  | timestamp        | NO   |     | CURRENT |                |\n");
    } else {
        printf("| column1     | varchar(255)     | YES  |     | NULL    |                |\n");
        printf("| column2     | int(11)          | YES  |     | NULL    |                |\n");
    }
    
    printf("+-------------+------------------+------+-----+---------+----------------+\n");
    
    return 0;
}

int gu_client_cmd_show_create_table(gu_client_context_t* ctx, const char* table) {
    if (!ctx || !table) return -1;
    
    if (!ctx->connected) {
        fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
        return 0;
    }
    
    // Trim whitespace and semicolon
    while (*table == ' ' || *table == '\t') table++;
    
    char table_name[256];
    strncpy(table_name, table, sizeof(table_name) - 1);
    table_name[sizeof(table_name) - 1] = '\0';
    
    // Remove trailing semicolon if present
    char* semicolon = strchr(table_name, ';');
    if (semicolon) *semicolon = '\0';
    
    // Remove trailing whitespace
    int len = strlen(table_name);
    while (len > 0 && (table_name[len-1] == ' ' || table_name[len-1] == '\t')) {
        table_name[--len] = '\0';
    }
    
    if (strlen(table_name) == 0) {
        fprintf(stderr, "Table name cannot be empty\n");
        return 0;
    }
    
    printf("CREATE TABLE statement for '%s':\n\n", table_name);
    
    // Mock CREATE TABLE statements
    if (strcasecmp(table_name, "users") == 0) {
        printf("CREATE TABLE `users` (\n");
        printf("  `id` int(11) NOT NULL AUTO_INCREMENT,\n");
        printf("  `name` varchar(50) DEFAULT NULL,\n");
        printf("  `email` varchar(100) DEFAULT NULL,\n");
        printf("  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n");
        printf("  PRIMARY KEY (`id`),\n");
        printf("  UNIQUE KEY `email` (`email`)\n");
        printf(") ENGINE=GuDB DEFAULT CHARSET=utf8;\n");
    } else if (strcasecmp(table_name, "products") == 0) {
        printf("CREATE TABLE `products` (\n");
        printf("  `id` int(11) NOT NULL AUTO_INCREMENT,\n");
        printf("  `name` varchar(100) NOT NULL,\n");
        printf("  `price` decimal(10,2) NOT NULL DEFAULT '0.00',\n");
        printf("  `category` varchar(50) DEFAULT NULL,\n");
        printf("  PRIMARY KEY (`id`)\n");
        printf(") ENGINE=GuDB DEFAULT CHARSET=utf8;\n");
    } else if (strcasecmp(table_name, "orders") == 0) {
        printf("CREATE TABLE `orders` (\n");
        printf("  `id` int(11) NOT NULL AUTO_INCREMENT,\n");
        printf("  `user_id` int(11) NOT NULL,\n");
        printf("  `product_id` int(11) NOT NULL,\n");
        printf("  `quantity` int(11) NOT NULL DEFAULT '1',\n");
        printf("  `order_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n");
        printf("  PRIMARY KEY (`id`),\n");
        printf("  KEY `user_id` (`user_id`),\n");
        printf("  KEY `product_id` (`product_id`)\n");
        printf(") ENGINE=GuDB DEFAULT CHARSET=utf8;\n");
    } else {
        printf("CREATE TABLE `%s` (\n", table_name);
        printf("  `column1` varchar(255) DEFAULT NULL,\n");
        printf("  `column2` int(11) DEFAULT NULL\n");
        printf(") ENGINE=GuDB DEFAULT CHARSET=utf8;\n");
    }
    
    return 0;
}

int gu_client_cmd_show_columns(gu_client_context_t* ctx, const char* table) {
    if (!ctx || !table) return -1;
    
    if (!ctx->connected) {
        fprintf(stderr, "Not connected to server. Use 'connect' command first.\n");
        return 0;
    }
    
    // This is essentially the same as DESCRIBE
    return gu_client_cmd_describe_table(ctx, table);
}